package com.espoir.shp.read04;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import org.geotools.data.*;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.shapefile.dbf.DbaseFileHeader;
import org.geotools.data.shapefile.dbf.DbaseFileReader;
import org.geotools.data.shapefile.files.ShpFiles;
import org.geotools.data.shapefile.shp.ShapefileReader;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * https://www.cnblogs.com/cugwx/p/3719195.html
 * JAVA用geotools读写shape格式文件
 * JAVA用geotools读写shape格式文件 （对应geotools版本：2.7.2）
 * <p>
 * （后面添加对应geotools 10.0版本的写法）
 * <p>
 * <p>
 * 读shape文件。
 * <p>
 * shape格式文件最少包含3个文件，他们的后缀是：.shp, .dbf, .shx。
 * <p>
 * .shp存储地理形状和位置信息，.dbf存储属性信息，.shx是索引文件。
 */
public class ReadWriteShape {
    public static void main(String[] args) {
        ReadWriteShape r = new ReadWriteShape();
        String path = "D:\\resource\\省界原始\\省界.shp";
        r.readSHP(path);

//        String p = new File("").getAbsolutePath();
//        p += "\\test.shp";
//        System.out.println("p = " + p);
//        r.write(p);
//        r.readAndShow();
    }

    /**
     * 单独读取DBF文件
     *
     * @param path
     */
    public void readDBF(String path) {

        DbaseFileReader reader = null;
        try {
            reader = new DbaseFileReader(new ShpFiles(path), false, Charset.forName("GBK"));
            DbaseFileHeader header = reader.getHeader();
            int numFields = header.getNumFields();
            //迭代读取记录
            while (reader.hasNext()) {
                try {
                    Object[] entry = reader.readEntry();
                    for (int i = 0; i < numFields; i++) {
                        String title = header.getFieldName(i);
                        Object value = entry[i];
                        System.out.println(title + "=" + value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                //关闭
                try {
                    reader.close();
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     * 读取3个文件，以point为例：
     *
     * @param path
     */
    public void readSHP(String path) {
        ShapefileDataStore shpDataStore = null;
        try {
            shpDataStore = new ShapefileDataStore(new File(path).toURI().toURL());
//            shpDataStore.setStringCharset(Charset.forName("GBK"));
            String typeName = shpDataStore.getTypeNames()[0];
            FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = null;
            featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) shpDataStore.getFeatureSource(typeName);
            FeatureCollection<SimpleFeatureType, SimpleFeature> result = featureSource.getFeatures();
            System.out.println(result.size());
            FeatureIterator<SimpleFeature> itertor = result.features();
            while (itertor.hasNext()) {
                SimpleFeature feature = itertor.next();
                Collection<Property> p = feature.getProperties();
                Iterator<Property> it = p.iterator();
                while (it.hasNext()) {
                    Property pro = it.next();
                    if (pro.getValue() instanceof Point) {
                        System.out.println("PointX = " + ((Point) (pro.getValue())).getX());
                        System.out.println("PointY = " + ((Point) (pro.getValue())).getY());
                    } else {
                        System.out.println(pro.getName() + " = " + pro.getValue());
                    }
                }
            }
            itertor.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void write(String filepath) {
        try {
            //创建shape文件对象
            File file = new File(filepath);
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            //定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(DefaultGeographicCRS.WGS84);
            tb.setName("shapefile");
            tb.add("the_geom", Point.class);
            tb.add("POIID", Long.class);
            tb.add("NAMEC", String.class);
            ds.createSchema(tb.buildFeatureType());
            ds.setCharset(Charset.forName("GBK"));
            //设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
            //写下一条
            SimpleFeature feature = writer.next();
            feature.setAttribute("the_geom", new GeometryFactory().createPoint(new Coordinate(116.123, 39.345)));
            feature.setAttribute("POIID", 1234567890l);
            feature.setAttribute("NAMEC", "某兴趣点1");
            feature = writer.next();
            feature.setAttribute("the_geom", new GeometryFactory().createPoint(new Coordinate(116.456, 39.678)));
            feature.setAttribute("POIID", 1234567891l);
            feature.setAttribute("NAMEC", "某兴趣点2");
            writer.write();
            writer.close();
            ds.dispose();

            //读取刚写完shape文件的图形信息
            ShpFiles shpFiles = new ShpFiles(filepath);
            ShapefileReader reader = new ShapefileReader(shpFiles, false, true, new
                    org.locationtech.jts.geom.GeometryFactory(), false);
            try {
                while (reader.hasNext()) {
                    System.out.println(reader.nextRecord().shape());
                }
            } finally {
                reader.close();
            }
        } catch (Exception e) {
        }
    }

    /**
     * 方法不可用，报错
      Exception in thread "main" java.lang.NoSuchMethodError: tec.uom.se.format.SimpleUnitFormat.getInstance()Ltec/uom/se/format/SimpleUnitFormat;
    */
    public void readAndShow() {
        //1.数据源选择 shp扩展类型的
        File file = JFileDataStoreChooser.showOpenFile("shp", null);
        if (file == null) {
            return;
        }

        //2.得到打开的文件的数据源
        FileDataStore store = null;
        SimpleFeatureSource featureSource = null;
        try {
            store = FileDataStoreFinder.getDataStore(file);


            //3.设置数据源的编码，防止中文乱码
            ((ShapefileDataStore) store).setCharset(Charset.forName("UTF-8"));


            /**
             * 使用FeatureSource管理要素数据
             * 使用Style（SLD）管理样式
             * 使用Layer管理显示
             * 使用MapContent管理所有地图相关信息
             */

            //4.以java对象的方式访问地理信息


            featureSource = store.getFeatureSource();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //5.创建映射内容，并将我们的shapfile添加进去
        MapContent mapContent = new MapContent();

        //6.设置容器的标题
        mapContent.setTitle("Appleyk's GeoTools");

        //7.创建简单样式
        Style style = SLD.createSimpleStyle(featureSource.getSchema());

        //8.显示【shapfile地理信息+样式】
        Layer layer = new FeatureLayer(featureSource, style);

        //9.将显示添加进map容器
        mapContent.addLayer(layer);

        //10.窗体打开，高大尚的操作开始
        JMapFrame.showMap(mapContent);

    }
}